package com.jf.nep;

import org.lwjgl.util.vector.Vector3f;

public class Mesh {
    public TexturedVertex[] vertices;
    public byte triangles[];
    public int textureId;
    
    public Mesh(int textureId) {
        this.textureId = textureId;
    }
    
    static Mesh createSurface(float w, float h, int textureId) {
        
        float hw = w / 2.0f;
        float hh = h / 2.0f;
        
        Mesh mesh = new Mesh(textureId);
        
        mesh.vertices = new TexturedVertex[] {
            TexturedVertex.createTextured(-hw, hh, -0.01f, 0, 0),
            TexturedVertex.createTextured(-hw, -hh, -0.01f, 0, h),
            TexturedVertex.createTextured(hw, -hh, -0.01f, w, h),
            TexturedVertex.createTextured(hw, hh, -0.01f, w, 0),
            
            TexturedVertex.createTextured(-hw, hh, 0, 0, 0),
            TexturedVertex.createTextured(-hw, -hh, 0, 0, h),
            TexturedVertex.createTextured(hw, -hh, 0, w, h),
            TexturedVertex.createTextured(hw, hh, 0, w, 0)
        };
        
        mesh.triangles = new byte[] {
                0,1,2,
                2,3,0,
                4+0,4+2,4+1,
                4+2,4+0,4+3};
        
        createFlatNormals(mesh);
        
        return mesh;
    }
            
    static void createSurfaceNormal(Mesh mesh, int offset) {
        Vector3f normal = new Vector3f();
        
        float[] v0 = mesh.vertices[mesh.triangles[offset]].getXYZW();
        float[] v1 = mesh.vertices[mesh.triangles[offset+1]].getXYZW();
        float[] v2 = mesh.vertices[mesh.triangles[offset+2]].getXYZW();
        
        Vector3f edge1 = new Vector3f(v1[0]-v0[0], v1[1]-v0[1], v1[2]-v0[2]);
        Vector3f edge2 = new Vector3f(v2[0]-v1[0], v2[1]-v1[1], v2[2]-v1[2]);
        
        Vector3f.cross(edge1, edge2, normal);
        normal.normalise();

        for (int i = offset; i < offset+3 ; i++) {
            mesh.vertices[mesh.triangles[i]].setNormal(normal.x, normal.y, normal.z);
        }
    }
    
    static void createFlatNormals(Mesh mesh) {
        for (int i = 0; i < mesh.triangles.length; i+= 3) {
            createSurfaceNormal(mesh, i);
        }
    }
        
    static Mesh createCube(float size, int textureId) {
        float hs = size / 2.0f;
        
        Mesh mesh = new Mesh(textureId);
        
        mesh.vertices = new TexturedVertex[] {
                // Front and back face
                TexturedVertex.createTextured(-hs, hs, -hs, 0, 0),
                TexturedVertex.createTextured(-hs, -hs, -hs, 0, 1),
                TexturedVertex.createTextured(hs, -hs, -hs, 1, 1),
                TexturedVertex.createTextured(hs, hs, -hs, 1, 0),
                
                TexturedVertex.createTextured(-hs, hs, hs,  0, 0),
                TexturedVertex.createTextured(-hs, -hs, hs,0, 1),
                TexturedVertex.createTextured(hs, -hs, hs, 1, 1),
                TexturedVertex.createTextured(hs, hs, hs, 1, 0),
                
                // Side faces
                TexturedVertex.createTextured(-hs, hs, -hs, 1, 1),
                TexturedVertex.createTextured(-hs, -hs, -hs, 0, 1),
                TexturedVertex.createTextured(hs, -hs, -hs, 0, 1),
                TexturedVertex.createTextured(hs, hs, -hs, 1, 1),
                
                TexturedVertex.createTextured(-hs, hs, hs,  1, 0),
                TexturedVertex.createTextured(-hs, -hs, hs,0, 0),
                TexturedVertex.createTextured(hs, -hs, hs, 0, 0),
                TexturedVertex.createTextured(hs, hs, hs, 1, 0),
                
                // Top faces
                TexturedVertex.createTextured(-hs, hs, -hs, 0, 1),
                TexturedVertex.createTextured(-hs, -hs, -hs, 0, 1),
                TexturedVertex.createTextured(hs, -hs, -hs, 1, 1),
                TexturedVertex.createTextured(hs, hs, -hs, 1, 1),
                
                TexturedVertex.createTextured(-hs, hs, hs,  0, 0),
                TexturedVertex.createTextured(-hs, -hs, hs,0, 0),
                TexturedVertex.createTextured(hs, -hs, hs, 1, 0),
                TexturedVertex.createTextured(hs, hs, hs, 1, 0)
        };
        
        mesh.triangles = new byte[] {
                0, 1, 2,   // Z constant
                2, 3, 0,
                
                4, 6, 5,
                6, 4, 7,
                
                8+0, 8+5, 8+1,   // X constant
                8+0, 8+4, 8+5,
                
                8+3, 8+2, 8+6,  
                8+3, 8+6, 8+7,  
                
                16+0, 16+3, 16+4,   // Y constant
                16+4, 16+3, 16+7,
                
                16+1, 16+6, 16+5,
                16+1, 16+2, 16+6
        };
        
        createFlatNormals(mesh);

        return mesh;
    }      
    
       

}
